#pragma once

#include "../common/platform.h"
#include <functional>

struct event;
struct event_base;


class LoopService;
class EZWatcher 
{
    EZWatcher(const EZWatcher&) = delete;
    void operator=(const EZWatcher&) = delete;
public:
    typedef std::function<void()> Handler;

    virtual ~EZWatcher();

    bool init();

    // @note It MUST be called in the event thread.
    void cancel();

    // @brief :
    // @param[IN] const Handler& cb - The callback which will be called when this event is canceled.
    // @return void -
	void set_cancel_Callback(const Handler& cb){
		cancel_callback_ = cb;
	}

    void clear_handler() { handler_ = Handler(); }

protected:
    // @note It MUST be called in the event thread.
    // @param timeout the maximum amount of time to wait for the event, or 0 to wait forever
    bool _watch(int timeout);

protected:
    EZWatcher(struct event_base* evbase, const Handler& handler);

    void _close();
    void _free_event();

    virtual bool _do_init() = 0;
    virtual void _do_close() {}

protected:
    struct event* event_;
    struct event_base* evbase_;
    bool attached_;
    Handler handler_;
    Handler cancel_callback_;
};

class PipeEventWatcher : public EZWatcher 
{
public:
	PipeEventWatcher(LoopService* loop, const Handler& handler);

    ~PipeEventWatcher();

    bool async_wait();
    void notify();
	ez_socket_t wfd() const { return pipe_[0]; }
private:
    virtual bool _do_init();
    virtual void _do_close();
	static void _pipe_handle_fun(ez_socket_t fd, short which, void* v);

	ez_socket_t pipe_[2]; // Write to pipe_[0] , Read from pipe_[1]
};

class TimerEventWatcher : public EZWatcher
{
public:
    TimerEventWatcher(LoopService* loop, const Handler& handler, int timeout);

    TimerEventWatcher(struct event_base* loop, const Handler& handler, int timeout);

    bool async_wait();

private:
    virtual bool _do_init();
	static void _time_event_handle_fun(ez_socket_t fd, short which, void* v);
private:
    int timeout_;
};



